﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Minio; 
using MinioStorage.Models;
using System.Diagnostics;
using System.Net;
using System.Security.AccessControl;
using System.Text.Json;

namespace MinioStorage.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class StorageController : ControllerBase
    {

        private readonly IConfiguration _configuration;
        public ILogger<StorageController> _Logger;
        public MinioClient _client { get; set; }
        public StorageController(IConfiguration configuration, ILogger<StorageController> logger, MinioClient client)
        {
            _client = client;
            _configuration = configuration;
            _Logger = logger;
        }

        //获取图片的返回类型
        public static Dictionary<string, string> contentTypDict = new Dictionary<string, string> {
               {"bmp","image/bmp" },
               {"jpg","image/jpeg"},
               {"jpeg","image/jpeg"},
               {"jpe","image/jpeg"},
               {"png","image/png"},
               {"gif","image/gif"},
               {"ico","image/x-ico"},
               {"tif","image/tiff"},
               {"tiff","image/tiff"},
               {"fax","image/fax"},
               {"wbmp","image//vnd.wap.wbmp"},
               {"rp","image/vnd.rn-realpix"} };

        #region 创建桶

        private async Task<bool> CheckOrCreateBucket(string bucketName)
        {
            var found = await _client.BucketExistsAsync(bucketName);
            if (!found)
            {
                await _client.MakeBucketAsync(bucketName);
                //设置只读策略
                var pObj = new
                {
                    Version = "2012-10-17",
                    Statement = new[]
                    {
                       new
                       {
                           Effect = "Allow",
                           Principal = new
                           {
                               AWS = new [] {"*"}
                           },
                           Action = new [] {"s3:GetBucketLocation", "s3:ListBucket"},
                           Resource = new []
                           {
                               $"arn:aws:s3:::{bucketName}"
                           }
                       },
                       new
                       {
                           Effect = "Allow",
                           Principal = new
                           {
                               AWS = new [] {"*"}
                           },
                           Action = new [] {"s3:GetObject"},
                           Resource = new []
                           {
                               $"arn:aws:s3:::{bucketName}/*"
                           }
                       }
                   }
                };
                var po = JsonSerializer.Serialize(pObj);
                await _client.SetPolicyAsync(bucketName, po);
                found = true;
            }
            return found;
        }

        #endregion

        #region 上传文件
        [HttpPost]
        public async Task<ServerResult> UploadFiles(UploadFilesDto uploadFilesDto)
        {
            var serverResult = new ServerResult<string[]>() { Success = false, Message = "上传失败", StatusCode = 401 };

            if (string.IsNullOrEmpty(uploadFilesDto?.ProjectCode))
            {
                serverResult.Message = "项目编码不能为空";
                return serverResult;
            }

            if (!uploadFilesDto.Files.Any())
            {
                serverResult.Message = "请求未包含任何上传文件，请检查";
                return serverResult;
            }

            //var config = _configuration.GetSection("S3Config").Get<List<StorageConfig>>();
            //var queryConfig = config.FirstOrDefault(x => x.ProjectCode == uploadFilesDto.ProjectCode);
            //if (queryConfig == null)
            //{
            //    serverResult.Message = $"未找到名为 {uploadFilesDto.ProjectCode} 项目配置属性";
            //    return serverResult;
            //}

            try
            {
                //1、检查存储桶是否存在，不存在则创建
                bool bucketExists = await CheckOrCreateBucket( uploadFilesDto.BucketName ?? "Defult");
                if (!bucketExists)
                {
                    serverResult.Message = "文件桶创建失败，请检查API到分布式存储之前的网络连接";
                    return serverResult;
                }
                var watch = new Stopwatch();
                foreach (var file in uploadFilesDto.Files)
                {
                    watch.Restart();
                    byte[] bytes = Array.Empty<byte>();
                    switch (file.FileType)
                    {
                        case "file":
                            bytes = Convert.FromBase64String(file.Base64);
                            break;
                        case "txt":
                            bytes = System.Text.Encoding.Default.GetBytes(file.Base64);
                            break;
                        default:
                            bytes = Convert.FromBase64String(file.Base64);
                            break;
                    }

                    Stream stream = new MemoryStream(bytes);

                    var request = new PutObjectArgs()
                        .WithBucket(uploadFilesDto.BucketName)
                        .WithContentType(contentTypDict[file.FileType])
                        .WithObject(uploadFilesDto.ProjectCode+"_"+file.ObjectKey+"."+file.FileType)
                        .WithObjectSize(stream.Length)
                        .WithStreamData(stream);

                    await _client.PutObjectAsync(request).ConfigureAwait(false);

                    watch.Stop();
                }
            }
            catch (Exception ex)
            {
                _Logger.LogError($"上传文件异常：{ex}");
                serverResult.Message = ex.Message;
                return serverResult;
            }

            var fileIds = uploadFilesDto.Files.Select(x => uploadFilesDto.ProjectCode + "_" + x.ObjectKey + "." + x.FileType).ToArray();
            serverResult.Data = fileIds;
            serverResult.Success = true;
            serverResult.Message = "上传成功";
            return serverResult;
        }
        #endregion

        #region 读取文件
        [HttpGet("{ProjectCode}/{BucketName}/{ObjectKey}")]
        public async Task<IActionResult> GetFilesAsync(string ProjectCode, string BucketName, string ObjectKey, string? FileType = "image")
        {
            try
            {
                var memoryStream = new MemoryStream();

                await _client.StatObjectAsync(BucketName, ObjectKey);
                await _client.GetObjectAsync(BucketName, ObjectKey, s =>{ s.CopyToAsync(memoryStream); });
                memoryStream.Position = 0;
                int sindex = ObjectKey.LastIndexOf(".") + 1;
                int eindex = ObjectKey.Length;
                string sekey = ObjectKey.Substring(sindex, (eindex-sindex));
               string contentTyp= contentTypDict[sekey];
                return File(memoryStream, contentTyp);
            }
            catch (Exception ex)
            {
                _Logger.LogError($"读取文件异常：{ex}");
                return Content(ex.Message);
            }
        }

        #endregion

    }
}
